package com.wind.httpProxyServer.test;


import com.wind.httpProxyServer.constants.HttpResponseStatus;
import com.wind.httpProxyServer.constants.Properties;
import com.wind.httpProxyServer.constants.RequestMethod;
import com.wind.httpProxyServer.httpMessage.HttpResponseMessage;
import com.wind.httpProxyServer.httpMessage.exception.ConnectServerError;
import com.wind.httpProxyServer.threadPools.ThreadPoolManager;
import com.wind.httpProxyServer.threads.https.ClientTranslateHttpsToServerThread;
import com.wind.httpProxyServer.threads.https.ServerTranslateHttpsToClientThread;
import com.wind.httpProxyServer.utils.SocketUtil;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class ProxyServer {
    private static final int PORT = 8888;
    private static Map<String, String> userMap = new HashMap<>();
    private static Map<String, String> authMap = new HashMap<>(); // 用于存储已通过身份验证的用户

    static {
        // 初始化用户信息，将用户名和密码存入 Map 中
        userMap.put("user1", "user1");
        userMap.put("user2", "pwd2");
    }

    public static void main(String[] args) {
        try  {
            ServerSocket serverSocket = new ServerSocket(PORT);
            System.out.println("代理服务器已启动，监听端口：" + PORT);
//            new Thread(){
//                @Override
//                public void run() {
//                    try {
//                        Thread.sleep(3000);
//                        serverSocket.close();
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    } catch (IOException e) {
//                        e.printStackTrace();
//                    }
//                }
//            }.start();
            while (true) {
                Socket clientSocket = serverSocket.accept();

                BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                PrintWriter out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()), true);

                // 获取客户端请求头
                try {
                    String requestLine = in.readLine();
                    System.out.println("requestLine:"+requestLine);
                    String header;
                    boolean flag = true;
                    String hostHeader ="";
                    while (true) {
                        header = in.readLine();
                        if (header == null || header.length() == 0) {
                            break;
                        }
                        // 如果请求头中已经携带了 Authorization 头部，则说明该客户端已经进行过身份验证
                        if (header.startsWith("Proxy-Authorization:")) {
                            String auth = header.substring(21).trim();
                            System.out.println("auth========"+auth);
                            if (authMap.containsValue(auth)) {
                                System.out.println("已通过身份验证，直接转发客户端请求");
                                flag = false;
                            }else{
                                String authString = new String(Base64.getDecoder().decode(header.substring(27).trim()));
                                String[] authParts = authString.split(":");
                                if(authParts.length==2){
                                    String username = authParts[0];
                                    String password = authParts[1];
                                    if (validateUser(username, password)) {
                                        // 身份验证成功，将用户名和密码存入 authMap 中，以便后续使用
                                        String auth0 = Base64.getEncoder().encodeToString(authString.getBytes());
                                        authMap.put(username, auth0);
                                        System.out.println("身份验证成功，已保存到 authMap 中");
                                        flag = false;
                                    }
                                }
                            }
                        }
                        if(header.startsWith("Host")){
                            hostHeader =header;
                        }
                    }
                    System.out.println("请求身份验证");
//                    if(flag){
//                        out.println("HTTP/1.1 407 Proxy Authentication Required");
//                        out.println("Proxy-Authenticate: Basic realm=\"Proxy Login\"");
//                        out.println();
//                        out.flush();
//
//                    }


                    String host = hostHeader;
                    int port = 80; // 默认端口
                    if (hostHeader.contains(":")) {
                        String[] hostArr = hostHeader.split(":");
                        host = hostArr[1].trim();
                        port = Integer.parseInt(hostArr[2]);
                    }

                    Socket targetServerSocket=null;
                    try {

                        targetServerSocket = SocketUtil.connectServer(host, port, Properties.ServerConnectTimeout);


                    } catch (ConnectServerError e) {
                        // e.printStackTrace();
                        SocketUtil.closeSocket(clientSocket, targetServerSocket);
                    }



                    targetServerSocket.setSoTimeout(Properties.ServerSocketReadTimeout); // 设置读取代理服务器Socket超时时间




                    HttpResponseMessage httpResponseMessage = new HttpResponseMessage(HttpResponseStatus._200);
                    SocketUtil.writeSocket(clientSocket.getOutputStream(), httpResponseMessage, false);

                    Thread clientToServer = new ClientTranslateHttpsToServerThread(clientSocket, targetServerSocket);
                    ThreadPoolManager.execute(clientToServer);

                    /*
                     * 将服务端数据转发给客户端
                     */
                    Thread serverToClient = new ServerTranslateHttpsToClientThread(clientSocket, targetServerSocket);
                    ThreadPoolManager.execute(serverToClient);

                }catch (Exception e){
                    e.printStackTrace();
                }finally {
//                    in.close();
//                    out.close();
               //     clientSocket.close();
                }


            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {

        }
    }

    private static boolean validateUser(String username, String password) {
        String pwd = userMap.get(username);
        return pwd != null && pwd.equals(password);
    }
}